/* FILE : ime.c */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <standard_im.h>

#include "server.h"
#include "ime.h"

typedef enum _IMECommand {		//IMM send to IME.
	//IME_INFO = 0,
	IME_IMM_VERSION = 0,
	IME_INITIALIZE,
	IME_FINALIZE,
	IME_HIDE,
	IME_UPDATE_DISPLAY,
	IME_UPDATE_SCREEN,
	IME_UPDATE_SPOT_LOCATION,
	IME_UPDATE_TRIGGER_PROPERTY,
	IME_PROCESS_IME_EVENT
} IMECommand;

typedef enum _IMMCommand {		//IME send to IMM.
	//IMM_VERSION = 0,
	IMM_IME_INFO = 0,
	IMM_OPEN_CONNECTION,
	IMM_CLOSE_CONNECTION,
	IMM_GET_CONNECTION_NUMBER,
	IMM_HAS_PENDING_EVENT,
	IMM_FILTER_EVENT,
	IMM_REGISTER_PROPERTIES,
	IMM_UPDATE_PROPERTY,
	IMM_SEND_IME_EVENT,
	IMM_SEND_KEY_EVENT,
	IMM_COMMIT_STRING,
	IMM_FORWARD_KEY_EVENT,
	IMM_READ_CONFIG,
	IMM_WRITE_CONFIG,
	IMM_LOAD_USER_DATA,
	IMM_FREE_USER_DATA,
	IMM_SAVE_USER_DATA
} IMMCommand;

typedef struct _IMBuffer {
	union {
		IMMCommand immCommand;
		IMECommand imeCommand;
	} command;

	size_t bufSize;
	void *buffer;
} IMBuffer;

static void ime_initialize(void);
static void ime_finalize(void);
static void ime_hide(void);
static void ime_update_display(int ic, const char *ic_uuid, const char *display);
static void ime_update_screen(int ic, const char *ic_uuid, const char *screen);
static void ime_update_spot_location(int ic, const char *ic_uuid, int x, int y);
static void ime_trigger_property(int ic, const char *ic_uuid, const char *property);
static void ime_process_ime_event(int ic, const char *ic_uuid, const void *buf, size_t buf_size);

IME_Helper_Functions ime_helper_functions;

int
ime_init()
{
	ime_helper_functions.initialize = ime_initialize;
	ime_helper_functions.finalize = ime_finalize;
	ime_helper_functions.hide = ime_hide;
	ime_helper_functions.update_display = ime_update_display;
	ime_helper_functions.update_screen = ime_update_screen;
	ime_helper_functions.update_spot_location = ime_update_spot_location;
	ime_helper_functions.trigger_property = ime_trigger_property;
	ime_helper_functions.process_ime_event = ime_process_ime_event;
	return 1;
}

static void
ime_initialize(void)
{
	return;
}

static void
ime_finalize()
{
	return;
}

static void
ime_hide(void)
{
	return;
}

static void
ime_update_display(int ic, const char *ic_uuid, const char *display)
{
	return;
}

static void
ime_update_screen(int ic, const char *ic_uuid, const char *screen)
{
	return;
}

static void
ime_update_spot_location(int ic, const char *ic_uuid, int x, int y)
{
#if DEBUG
	fprintf(stderr, "XAUX : ime update spot location\n");
#endif
	char *unibuf;
	size_t unisize;
	int *i;

	unisize = sizeof(IMECommand) + sizeof(int)*3;
	unibuf = (char *)malloc(unisize);

	//set ime command
	i = (int *)unibuf;
	*i = IME_UPDATE_SPOT_LOCATION;

	//set buffer len
	i++;
	*i = sizeof(int)*2;

	//set buffer
	i++;
	*i = x;
	i++;
	*i = y;
#if DEBUG
	fprintf(stderr, "XAUX : server send update spot location command %d\n",
			IME_UPDATE_SPOT_LOCATION);
#endif
	server_send(unibuf, (int)unisize);
	free(unibuf);
}

static void
ime_trigger_property(int ic, const char *ic_uuid, const char *property)
{
	return;
}

static void
ime_process_ime_event(int ic, const char *ic_uuid, const void *buf, size_t buf_size)
{
#if DEBUG
	fprintf(stderr, "XAUX : ime process ime event\n");
#endif
	char *unibuf;
	int unilen;
	int *i;

	unilen = sizeof(int)*2 + buf_size;
	unibuf = (char *)malloc(unilen);

	i = (int *)unibuf;

	//set ime command
	*i = IME_PROCESS_IME_EVENT;

	//set buffer size
	i++;
	*i = buf_size;

	//set buffer
	i++;
	memcpy((char *)i, buf, buf_size);

#if DEBUG
	fprintf(stderr, "XAUX : server send process ime event command %d\n",
			*(int *)unibuf);
#endif
	server_send((char *)unibuf, (int)buf_size);
	free(unibuf);
}
